#!/bin/bash
# Copyright (c) 2020 maminjie <maminjie1@huawei.com>
# SPDX-License-Identifier: MulanPSL-2.0

readonly COLOR_NONE="\033[0m"
readonly COLOR_RED="\033[0;31m"
readonly COLOR_GREEN="\033[0;32m"
readonly COLOR_YELLOW="\033[0;33m"


yum_binrepo="--repo repo-r --repo repo-u"
yum_srcrepo="--repo repo-r-src --repo repo-u-src"

# How to generate sql file?
# Example:
#   wget https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/30/Everything/source/tree/repodata/xxxx-primary.sqlite.xz
#   wget https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/30/Everything/aarch64/os/repodata/yyyy-primary.sqlite.xz
#   wget https://repo.openeuler.org/openEuler-20.09/source/repodata/xxx-primary.sqlite.bz2
#   wget https://repo.openeuler.org/openEuler-20.09/everything/aarch64/repodata/yyy-primary.sqlite.bz2
#   xz -d xxxx-primary.sqlite.xz                # bunzip2 -d xxx-primary.sqlite.bz2
#   sqlite3 xxxx-primary.sqlite .dump > xx.sql
# Notes:
#   You need to prepare sql files for bin and src
#
sql_bin_file=""
sql_src_file=""

usage() {
    echo "Usage: obs [GLOBALOPTS] SUBCOMMAND [OPTS] [ARGS...]"
    echo "or: obs help SUBCOMMAND"
    echo ""
    echo "obs assistant tools."
    echo "Type 'obs help <subcommand>' for help on a specific subcommand."
    echo ""
    echo "Commands:"
    echo "      branch (br)             Branch some packages"
    echo "      checkout (co)           Check out content from the repository"
    echo "      importsrcpkg (isp)      Import some new packages from src.rpm"
    echo "      pkgresults (pr)         Shows package-wide build results"
    echo "      changename (cn)         Remove the _service:xxx: prefix of package filename"
    echo "      setflag (sf)            Modify or set a defined flag for package"
    echo "      unresolved (ur)         Analyse the unresolved packages"
    echo "      requiredby (rb)         Analyse the required packages"
    echo "      buildrequiredby (brb)   Analyse the build required packages"
    echo "      whatprovides (wp)       Show only results that provide"
    echo "      whatrequires (wr)       Shows results that requires package provides and files"
    echo "      whatbuildrequires (wbr) Shows results that requires package provides and files"
    echo "      requires (rq)           Display capabilities that the package install depends on"
    echo "      provides (prov)         Display capabilities provided by the package"
    echo "      installdep (idep)       Display the package install dependencies and all requires of dependent packages"
    echo "      buildrequires (brq)     Display capabilities that the package build depends on"
    echo "      builddep (bdep)         Display the package build dependencies and all requires of dependent packages"
    echo "      buildinfo (binfo)       Display the package build infos"
    echo "      pkgship (ps)            Display the package ship about build and install dependencies"
    echo "      getbin (gb)             Get binary from the obs"
    echo "      getbinaries (gbs)       Get binaries from the obs"
    echo "      getbinlist(gbl)         Get binary list"
    echo "      getfile (gf)            Get file from the obs"
    echo "      filterout (flo)         Filter out the packages by obs projects"
    echo "      list (ls)               list the packages of project"
    echo "      help (?, h)             Give detailed help on a specific sub-command"
    echo ""
    echo "Global Options:"
    echo "      -h, --help              Show this help message and exit"
    echo ""
}

usage_branch() {
    echo "branch (br): Branch some packages"
    echo ""
    echo "usage:"
    echo "      obs br SOURCEPROJECT TARGETPROJECT PKGLIST|LISTFILE"
    echo ""
}

usage_checkout() {
    echo "checkout (co): Check out content from the repository"
    echo ""
    echo "usage:"
    echo "      obs co SOURCEPROJECT PKGLIST|LISTFILE"
    echo "      obs co PKGLIST|LISTFILE                         # current dir must be obs project"
    echo "      obs co SOURCEPROJECT/PACKAGE"
    echo ""
}

usage_importsrcpkg() {
    echo "importsrcpkg (isp): Import some new packages from src.rpm"
    echo ""
    echo "usage:"
    echo "      obs importsrcpkg PROJECT YUMREPO PKGLIST|LISTFILE"
    echo ""
}

usage_pkgresults() {
    echo "pkgresults (pr): Shows package-wide build results"
    echo ""
    echo "usage:"
    echo "      obs pkgresults PACKAGE"
    echo ""
}

usage_changename() {
    echo "changename (cn): Remove the _service:xxx: prefix of package filename"
    echo ""
    echo "usage:"
    echo "      obs changename"
    echo ""
}

usage_setflag() {
    echo "setflag (sf): Modify or set a defined flag for package"
    echo ""
    echo "usage:"
    echo "      obs setflag PROJECT REPO ARCH FLAG STATUS PKGLIST|LISTFILE"
    echo ""
    echo "parameter:"
    echo "      REPO: setflag for given repository (all/..)"
    echo "      ARCH: setflag for given arch (all/..)"
    echo "      FLAG: modify this flag (build/publish/..) for setflag command"
    echo "      STATUS: enable or disable for setflag command"
    echo ""
    echo "example:"
    echo "      obs setflag PROJECT all all build disable PACKAGE"
    echo "      obs setflag PROJECT standard_aarch64 all build disable PACKAGE"
    echo ""
}

usage_unresolved() {
    echo "unresolved (ur): Analyse the unresolved packages"
    echo ""
    echo "usage:"
    echo "      obs ur PROJECT REPO ARCH"
    echo "      obs ur PROJECT REPO ARCH PKGLIST|LISTFILE"
    echo ""
}

usage_requiredby() {
    echo "requiredby (rb): Analyse the required packages"
    echo ""
    echo "usage:"
    echo "      obs rb PROJECT PACKAGE"
    echo "      obs rb PACKAGE"
    echo "      obs rb PACKAGE BIN.sql SRC.sql"
    echo ""
}

usage_buildrequiredby() {
    echo "buildrequiredby (brb): Analyse the build required packages"
    echo ""
    echo "usage:"
    echo "      obs brb PACKAGE"
    echo "      obs brb PACKAGE BIN.sql SRC.sql"
    echo ""
}

usage_whatprovides() {
    echo "whatprovides (wp): Show only results that provide REQ"
    echo ""
    echo "usage:"
    echo "      obs wp REQ"
    echo "      obs wp REQ BIN.spl"
    echo ""
}

usage_whatrequires() {
    echo "whatrequires (wr): Shows results that requires package provides and files"
    echo ""
    echo "usage:"
    echo "      obs wr REQ"
    echo "      obs wr REQ BIN.sql"
    echo ""
}

usage_whatbuildrequires() {
    echo "whatbuildrequires (wbr): Shows results that requires package provides and files"
    echo ""
    echo "usage:"
    echo "      obs wbr REQ"
    echo "      obs wbr REQ SRC.sql"
    echo ""
}

usage_requires() {
    echo "requires (rq): Display capabilities that the package install depends on"
    echo ""
    echo "usage:"
    echo "      obs rq PACKAGE"
    echo "      obs rq SPEC"
    echo "      obs rq PACKAGE BIN.sql SRC.sql"
    echo ""
}

usage_provides() {
    echo "provides (prov): Display capabilities provided by the package"
    echo ""
    echo "usage:"
    echo "      obs prov PROJECT PACKAGE"
    echo "      obs prov PACKAGE"
    echo ""
}

usage_installdep() {
    echo "installdep (idep): Display the package install dependencies and all requires of dependent packages"
    echo ""
    echo "usage:"
    echo "      obs idep PKGLIST|LISTFILE [OUTFILE]"
    echo "      obs idep PkGLIST|LISTFILE BIN.sql SRC.sql [OUTFILE]"
    echo ""
}

usage_buildrequires() {
    echo "buildrequires (brq): Display capabilities that the package build depends on"
    echo ""
    echo "usage:"
    echo "      obs brq SPEC"
    echo "      obs brq PACKAGE BIN.sql SRC.sql"
    echo ""
}

usage_builddep() {
    echo "builddep (bdep): Display the package build dependencies and all requires of dependent packages"
    echo ""
    echo "usage:"
    echo "      obs bdep PROJECT/REPO/ARCH/PACKAGE"
    echo "      obs bdep PKGLIST|LISTFILE [OUTFILE]"
    echo "      obs bdep PKGLIST|LISTFILE BIN.sql SRC.sql [OUTFILE]"
    echo ""
}

usage_buildinfo() {
    echo "buildinfo (binfo): Display the package build infos"
    echo ""
    echo "usage:"
    echo "      obs binfo PROJECT/REPO/ARCH/PACKAGE"
    echo ""
}

usage_pkgship() {
    echo "pkgship (ps):  Display the package ship about build and install dependencies"
    echo ""
    echo "usage:"
    echo "      obs ps PKGLIST|LISTFILE [OUTFILE]"
    echo "      obs ps PKGLIST|LISTFILE BIN.sql SRC.sql [OUTFILE]"
    echo ""
}

usage_getbin() {
    echo "getbin (gb): Get binary from the obs"
    echo ""
    echo "usage:"
    echo "      obs getbin URL"
    echo ""
    echo "example:"
    echo "      obs getbin https://xxx/project/package/repo/arch/binaryname"
    echo "      obs getbin project/package/repo/arch/binaryname"
    echo ""
    echo "notes:"
    echo "      URL: you can copy the url from the obs directly"
    echo ""
}

usage_getbinaries() {
    echo "getbinaries (gbs): Get binaries from the obs"
    echo ""
    echo "usage:"
    echo "      obs gbs PROJECT REPO ARCH PKGLIST|LISTFILE"
    echo ""
}

usage_getbinlist() {
    echo "getbinlist (gbl): Get binary list"
    echo ""
    echo "usage:"
    echo "      obs gbl PROJECT PACKAGE"
    echo ""
}

usage_getfile() {
    echo "getfile (gf): Get file from the obs"
    echo ""
    echo "usage:"
    echo "      obs gf URL"
    echo ""
    echo "example:"
    echo "      obs gf https://xxx/project/package/filename?xxxx"
    echo "      obs gf project/package/filename"
    echo ""
    echo "notes:"
    echo "      URL: you can copy the url from the obs directly"
    echo ""
}

usage_filterout() {
    echo "filterout (flo): Filter out the packages by obs projects"
    echo ""
    echo "usage:"
    echo "      obs flo PRJLIST|LISTFILE PKGLIST|LISTFILE"
    echo ""
}

usage_list() {
    echo "list (ls): list the packages of project"
    echo ""
    echo "usage:"
    echo "      obs ls PROJECT REPO ARCH STATE"
    echo ""
    echo "parameter:"
    echo "      STATE: package state, value as follows:"
    echo "          s scheduled"
    echo "          S signing"
    echo "            disabled"
    echo "          B broken"
    echo "          f finished"
    echo "          b blocked"
    echo "          % building"
    echo "          L locked"
    echo "          . succeeded"
    echo "          U unresolvable"
    echo "          d dispatching"
    echo "          F failed"
    echo "          x excluded"
    echo ""
}

get_list() {
    local lst=""

    if [ -f "$1" ]; then
        lst=$(cat $1)
    else
        lst=$1
    fi

    echo $lst
}

# do_branch(src_prj, dst_prj, pkgs)
do_branch() {
    if [ $# != 3 ]; then
        usage_branch; exit
    fi
    local pkgs=$(get_list "$3")

    k=1
    for pkg in $pkgs; do
        echo "$k) branching $1/$pkg"
        osc branch $1 $pkg $2 2> /dev/null
        ((k++))
    done
}

check_obs_project() {
    ls -a .osc | grep _project > /dev/null 2>&1
    if [ $? != 0 ]; then
        return 1
    fi
    return 0
}

# do_checkout(src_prj, pkgs)
# do_checkout(pkgs)
# do_checkout(src_prj/pkg)
do_checkout() {
    local prj=""
    local pkgs=""
    if [ $# == 2 ]; then
        prj=$1
        pkgs=$(get_list "$2")
    elif [ $# == 1 ]; then
        # prj/pkg
        eval $(echo "$1" | awk -F "/" '{
            if (NF >= 2) {
                printf("prj=%s;pkgs=%s;", $(NF-1), $NF)
            }
        }')
        if [ -z "$prj" ]; then
            check_obs_project
            if [ $? != 0 ]; then
                usage_checkout; exit
            fi
            pkgs=$(get_list "$1")
        fi
    else
        usage_checkout; exit
    fi

    k=1
    for pkg in $pkgs; do
        local pkg_path=$prj/$pkg
        if [ -z "$prj" ]; then
            pkg_path=$pkg
        fi
        echo "$k) checking out $pkg_path"
        osc co $pkg_path 2> /dev/null
        pushd $pkg_path
        do_changename
        popd
        ((k++))
    done
}

# do_importsrcpkg(project, yumrepo, pkgs)
do_importsrcpkg() {
    if [ $# != 3 ]; then
        usage_importsrcpkg; exit
    fi
    local prj=$1
    local repo=$2
    local pkgs=$(get_list "$3")

    for pkg in $pkgs; do
        yumdownloader --source $pkg --repo $repo
        if [ $? != 0 ]; then
            continue
        else
            local prj_tmp=$(osc search --package "$pkg" | grep "${prj##*/}" | awk '{print $1}')
            if [ "$prj" = "$prj_tmp" ]; then
                echo "$pkg exist"
                continue;
            fi
            osc importsrcpkg ${pkg}*.src.rpm -p $prj -n $pkg
            cd $prj/$pkg
            osc ar
            osc ci -m "init"
            cd -
        fi
    done
}

do_pkgresults() {
    if [ $# != 1 ]; then
        usage_pkgresults; exit
    fi
    local package=$1
    local projects=$(osc search --package "$package" 2> /dev/null | grep -A20 "# Project" | grep -v "# Project" | awk '{print $1}')

    i=1
    for prj in $projects; do
        results=$(osc results $prj $package 2> /dev/null)
        echo -e "${COLOR_YELLOW}$i) $prj${COLOR_NONE}"
        echo "${results}" | awk -F '\n' '{
            for(k=1;k<=NF;k++) {
                printf("\t%s\n", $k)
            }
        }'
        ((i++))
    done
}

do_changename() {
    service=_service

    if [ ! -f $service ]; then
        usage_changename; exit;
    fi

    if [ $(ls $service* | wc -l) == 1 ]; then
        osc up -S 2> /dev/null
    fi

    rm -f $service

    for file in $(ls | grep -v .osc); do
        new_file=${file##*:}
        mv $file $new_file
    done
}

# refer to https://build.opensuse.org/apidocs/index
do_setflag() {
    if [ $# != 6 ]; then
        usage_setflag; exit
    fi
    local prj=$1
    local repo=$2
    local arch=$3
    local flag=$4
    local status=$5
    local pkgs=$(get_list "$6")
    local content=""

    for pkg in $pkgs; do
        if [ "$repo" = "all" ]; then
            if [ "$arch" = "all" ]; then
                content="/source/${prj}/${pkg}?cmd=set_flag&flag=${flag}&status=${status}"
            else
                content="/source/${prj}/${pkg}?cmd=set_flag&arch=${arch}&flag=${flag}&status=${status}"
            fi
        else
            if [ "$arch" = "all" ]; then
                content="/source/${prj}/${pkg}?cmd=set_flag&repository=${repo}&flag=${flag}&status=${status}"
            else
                content="/source/${prj}/${pkg}?cmd=set_flag&repository=${repo}&arch=${arch}&flag=${flag}&status=${status}"
            fi
        fi
        echo "set $status for $prj/$pkg ($repo/$arch) $flag flag"
        osc api -X POST "$content" 2> /dev/null
    done
}

check_yumrepo() {
    if [ ! -f "/etc/yum.repos.d/fancy.repo" ]; then
        echo "Please copy the fancy.repo to /etc/yum.repos.d firstly!"
        return 1
    fi
    return 0
}

__find_project() {
    local result_file=$1
    local rely_pkgs=$(cat $result_file | awk '{print $4}' | sort | uniq)

    printf "%s\t%s\n" PKG PRJ
    for x in $rely_pkgs; do
        local prjs=$(osc search --package "$x" | awk '{print $1}' | tail -n +4)
        for y in $prjs; do
            printf "%s\t%s\n" $x $y
        done
    done | tee project_result.txt
}

# sql_get_pkgkey(pkg, sqlfile)
sql_get_pkgkey() {
    local pkg="$1"
    pkg=$(echo "$pkg" | sed 's/\+/\\+/g')
    local key=$(grep -wE "INSERT INTO packages VALUES\([0-9]+,'[A-Za-z0-9]+','$pkg'" "$2" |\
        sed -r 's/.*VALUES\(([0-9]+),.*/\1/g')
    echo "$key"
}

# sql_get_pkgbin(key, sqlfile)
#   sqlfile:
#       sqlbinfile - the bin is rpm package name
#       sqlsrcfile - the bin is src.rpm package name
sql_get_pkgbin() {
    local pkg=$(grep -w "INSERT INTO packages VALUES" "$2" | grep "VALUES($1," |\
        awk -F ',' '{print $3}' | sed "s/'//g")
    echo "$pkg"
}

# sql_get_pkgsrc(bin, sqlbinfile)
sql_get_pkgsrc() {
    local bin="$1"
    bin=$(echo "$bin" | sed 's/\+/\\+/g')
    local pkginfo=$(grep -wE "INSERT INTO packages VALUES\([0-9]+,'[A-Za-z0-9]+','$bin'" "$2")
    eval $(echo "$pkginfo" | awk -F "," '{
        printf("version=%s;summary=%s;src=%s;", $5, $7, $(NF-9))
    }')
    local pattern="-($version|$summary.src.rpm)"
    pattern=$(echo "$pattern" | sed 's/\+/\\+/g')
    src=$(echo "$src" | sed -r "s/$pattern//g")
    echo "$src"
}

# sql_requires(pkgkey, sqlfile)
sql_requires() {
    local reqs=$(grep -w "INSERT INTO requires VALUES" "$2" | grep ",$1," |\
        sed -r 's/.*VALUES\(([^,]+).*/\1/g' | sed "s/'//g" | sed 's/^(//' | sed 's/ \+.*//')
    echo "$reqs"
}

# sql_provides(pkgkey, sqlbinfile)
sql_provides() {
    local pros=$(grep -w "INSERT INTO provides VALUES" "$2" | grep ",$1)" |\
        sed -r 's/.*VALUES\(([^,]+).*/\1/g' | sed "s/'//g")
    echo "$pros"
}

# sql_whatprovides(sym, sqlbinfile)
sql_whatprovides() {
    local key=$(grep -w "INSERT INTO provides VALUES" "$2" | grep -w "'$1'" |\
        awk -F ',' '{print $6}' | sed -r 's/([0-9]+).*/\1/g' | head -n1)
    local bin=$(sql_get_pkgbin "$key" "$2")
    echo "$bin"
}

# sql_whatrequires(sym, sqlfile)
#   sqlfile:
#       sqlbinfile - the bin is rpm package name
#       sqlsrcfile - the bin is src.rpm package name
sql_whatrequires() {
    local keys=$(grep -w "INSERT INTO requires VALUES" "$2" | grep -w "'$1'" |\
        awk -F ',' '{print $6}')
    local array=()
    for key in $keys; do
        local bin=$(sql_get_pkgbin "$key" "$2")
        array=(${array[@]} $bin)
    done
    bins=$(echo "${array[*]}" | sed 's/ /\n/g')
    echo "$bins"
}

# sql_get_srcrpm(pkg, sqlsrcfile)
sql_get_srcrpm() {
    local srcrpm=""
    local pkg="$1"
    pkg=$(echo "$pkg" | sed 's/\+/\\+/g')
    local pkginfo=$(grep -wE "INSERT INTO packages VALUES\([0-9]+,'[A-Za-z0-9]+','$pkg'" "$2")
    if [ -n "$pkginfo" ]; then
        srcrpm=$(echo "$pkginfo" | awk -F ',' '{print $(NF-2)}' | sed "s/'//g")
        srcrpm=${srcrpm##*/}
    fi
    echo "$srcrpm"
}

# sql_get_subpkgs(srcrpm, sqlbinfile)
sql_get_subpkgs() {
    local bins=$(grep -w "'$1'" "$2" | grep -w "INSERT INTO packages VALUES" |\
        awk -F ',' '{print $3}' | sed "s/'//g")
    echo "$bins"
}

# get_bin_pkgname(pkgs)
get_bin_pkgname() {
    for p in $1; do
        name=$(dnf info $p $yum_binrepo 2>/dev/null | grep "Name" | head -n 1 | awk '{print $3}')
        if [ -n "$name" ]; then
            echo "$name"
        else
            name=$(echo "$p" | sed 's/-[[:digit:]]\+.*//')
            echo "$name"
        fi
    done
}

# get_src_pkgname(pkgs)
get_src_pkgname() {
    for p in $1; do
        name=$(dnf info $p $yum_srcrepo 2>/dev/null | grep "Name" | head -n 1 | awk '{print $3}')
        if [ -n "$name" ]; then
            echo "$name"
        fi
    done
}

# get_whatprovides(symbol)
get_whatprovides() {
    local bin=""
    if [ -f "$sql_bin_file" ]; then
        bin=$(sql_whatprovides "$1" "$sql_bin_file")
    else
        #bin=$(dnf repoquery --whatprovides "$1" $yum_binrepo -q 2>/dev/null | head -n1 | sed 's/-[[:digit:]]\+.*//')
        bin=$(dnf repoquery --whatprovides "$1" $yum_binrepo -q 2>/dev/null | head -n1)
        bin=$(get_bin_pkgname "$bin" | uniq)
    fi
    echo "$bin"
}

# get_whatrequires(symbol)
get_whatrequires() {
    local bins=""
    if [ -f "$sql_bin_file" ]; then
        bins=$(sql_whatrequires "$1" "$sql_bin_file" | uniq)
    else
        #bins=$(dnf repoquery --whatrequires "$1" $yum_binrepo 2> /dev/null | sed 's/-[[:digit:]]\+.*//' | uniq)
        bins=$(dnf repoquery --whatrequires "$1" $yum_binrepo 2> /dev/null | uniq)
        bins=$(get_bin_pkgname "$bins" | uniq)
    fi
    echo "$bins"
}

# get_whatbuildrequires(symbol)
get_whatbuildrequires() {
    local srcs=""
    if [ -f "$sql_src_file" ]; then
        srcs=$(sql_whatrequires "$1" "$sql_src_file" | uniq)
    else
        #srcs=$(dnf repoquery --whatrequires "$1" $yum_srcrepo 2> /dev/null | sed 's/-[[:digit:]]\+.*//' | uniq)
        srcs=$(dnf repoquery --whatrequires "$1" $yum_srcrepo 2> /dev/null | uniq)
        srcs=$(get_src_pkgname "$srcs" | uniq)
    fi
    echo "$srcs"
}

# get_requires(pkg)
get_requires() {
    local reqs=""
    if [ -f "$sql_bin_file" ]; then
        local pkgkey=$(sql_get_pkgkey "$1" "$sql_bin_file")
        reqs=$(sql_requires "$pkgkey" "$sql_bin_file")
    else
        reqs=$(dnf repoquery "$1" --requires $yum_binrepo 2> /dev/null | sed 's/^(//' | sed 's/ \+.*//')
    fi
    echo "$reqs"
}

# get_provides(pkg)
get_provides() {
    local pros=""
    if [ -f "$sql_bin_file" ]; then
        local pkgkey=$(sql_get_pkgkey "$1" "$sql_bin_file")
        pros=$(sql_provides "$pkgkey" "$sql_bin_file")
    else
        pros=$(dnf repoquery "$1" --provides $yum_binrepo 2> /dev/null | sed 's/^(//' | sed 's/ \+.*//')
    fi
    echo "$pros"
}

# get_buildrequires(pkg)
get_buildrequires() {
    local reqs=""
    if [ -f "$sql_src_file" ]; then
        local pkgkey=$(sql_get_pkgkey "$1" "$sql_src_file")
        reqs=$(sql_requires "$pkgkey" "$sql_src_file")
    else
        reqs=$(dnf repoquery "$1" --requires $yum_srcrepo 2> /dev/null | sed 's/^(//' | sed 's/ \+.*//')
    fi
    echo "$reqs"
}

# get_source(bin)
get_source() {
    local src=""
    if [ -f "$sql_bin_file" ]; then
        src=$(sql_get_pkgsrc "$1" "$sql_bin_file")
    else
        #src=$(dnf repoquery -q -i "$1" $yum_binrepo | grep Source | head -n1 | awk '{print $3}' | sed 's/-[[:digit:]]\+.*//')
        src=$(dnf repoquery -q -i "$1" $yum_binrepo | grep Source | grep -v "None" | head -n1 | awk '{print $3}' | sed 's/\.rpm$//g')
        src=$(get_bin_pkgname "$src" | uniq)
    fi
    echo "$src"
}

# do_unresolved(prj, repo, arch)
do_unresolved() {
    if [ $# -lt 3 ]; then
        usage_unresolved; exit
    fi
    check_yumrepo
    if [ $? != 0 ]; then
        exit
    fi
    local obs_project=$1
    local obs_repo=$2
    local obs_arch=$3
    local unresolved_pkgs=""
    if [ -n "$4" ]; then
        unresolved_pkgs=$(get_list "$4")
    else
        unresolved_pkgs=$(osc pr $obs_project -s U -r $obs_repo -a $obs_arch -q -V 2> /dev/null | sed 1d | sed '$d' | sed '$d' | awk '{print $2}')
    fi

    # do query
    printf "%s\t%s\t%s\t%s\n" PKG DEP BIN SRC
    for x in $unresolved_pkgs; do
        relys=$(osc r $obs_project $x -r $obs_repo -a $obs_arch -v 2> /dev/null | grep -v unresolv | awk '{print $3}' | sed -r 's/^\(//g')
        for y in $relys; do
            bin=$(get_whatprovides "$y")
            if [ -z "$bin" ]; then
                bin="Not-Found"
                src="Not-Found"
            else
                src=$(get_source "$bin")
                if [ -z "$src" ]; then
                    src=$bin
                fi
            fi
            printf "%s\t%s\t%s\t%s\n" $x $y $bin $src
        done
    done
}

# __do_requiredby(pkgarray)
__do_requiredby() {
    local pkgs=($1)
    local rbpkgs=()

    printf "%s|%s|%s|%s\n" "# Package" "# Provides" "# Required-bin" "# Required-src"
    for ((i=0;i<${#pkgs[@]};i++)); do
        local pkg=${pkgs[$i]}
        local pros=$(get_provides "$pkg")
        for pro in $pros; do
            local reqbins=$(get_whatrequires "$pro")
            for bin in $reqbins; do
                local reqsrc=$(get_source "$bin")
                if [ -z "$reqsrc" ]; then
                    continue
                fi
                printf "%s|%s|%s|%s\n" $pkg $pro $bin $reqsrc
                if [ $(array_contain "${rbpkgs[*]}" "$reqsrc") == 0 ]; then
                    rbpkgs=(${rbpkgs[@]} $reqsrc)
                fi
            done
        done
    done
    printf "|||\n"
    rbpkgs=($(array_uniq "${rbpkgs[*]}"))
    printf "\n# RequiredBy:\n"
    for ((i=0;i<${#rbpkgs[@]};i++)); do
        echo "${rbpkgs[$i]}"
    done
}

# get_bins_fromobs(prj, pkg)
get_bins_fromobs() {
    local bins=""
    local prj=$1
    local pkg=$2
    local results=$(osc results $prj $pkg 2> /dev/null)
    local repo_arch=$(echo "$results" | awk '{print $1"/"$2}' | grep "aarch64")
    if [ -n "$repo_arch" ]; then
        # /build/project/repo/arch/package
        local content="/build/$prj/$repo_arch/$pkg"
        #bins=$(osc api -X GET "$content" 2> /dev/null | grep ".rpm" | awk '{print $2}' | awk -F '=' '{print $2}' |\
        #    sed 's/"//g' | sed 's/-[[:digit:]]\+.*//' | uniq)
        bins=$(osc api -X GET "$content" 2> /dev/null | grep ".rpm" | awk '{print $2}' | awk -F '=' '{print $2}' | sed 's/"//g' | sed 's/\.rpm$//g' | uniq)
        bins=$(get_bin_pkgname "$bins" | uniq)
    fi
    echo "$bins"
}

# get_bins_fromsqlfile(pkg)
get_bins_fromsqlfile() {
    local bins=""
    local srcrpm=$(sql_get_srcrpm "$1" "$sql_src_file")
    if [ -n "$srcrpm" ]; then
        bins=$(sql_get_subpkgs "$srcrpm" "$sql_bin_file")
    fi
    echo "$bins"
}

# do_requiredby(prj, pkg)
# do_requiredby(pkg)
# do_requiredby(pkg, sqlbinfile, sqlsrcfile)
do_requiredby() {
    local subpkgs=()
    if [ $# == 1 ] || [ $# == 2 ]; then
        check_yumrepo
        if [ $? != 0 ]; then
            exit
        fi
        if [ $# == 2 ]; then
            local bins=$(get_bins_fromobs "$1" "$2")
            if [ -z "$bins" ]; then
                exit
            fi
            subpkgs=($bins)
        else
            subpkgs=($1)
        fi
    elif [ $# == 3 ]; then
        sql_bin_file=$2
        sql_src_file=$3
        local bins=$(get_bins_fromsqlfile "$1")
        subpkgs=($bins)
    else
        usage_requiredby; exit
    fi
    __do_requiredby "${subpkgs[*]}" | column -t -s '|'
}

# __do_buildrequiredby(pkgarray)
__do_buildrequiredby() {
    local pkgs=($1)
    local rbpkgs=()

    printf "%s|%s|%s\n" "# Package" "# Provides" "# BuildRequired-src"
    for ((i=0;i<${#pkgs[@]};i++)); do
        local pkg=${pkgs[$i]}
        local pros=$(get_provides "$pkg")
        for pro in $pros; do
            local reqsrcs=$(get_whatbuildrequires "$pro")
            if [ -z "$reqsrcs" ]; then
                continue
            fi
            for reqsrc in $reqsrcs; do
                printf "%s|%s|%s\n" $pkg $pro $reqsrc
            done
            rbpkgs=(${rbpkgs[@]} $reqsrcs)
        done
    done
    printf "||\n"
    rbpkgs=($(array_uniq "${rbpkgs[*]}"))
    printf "\n# BuildRequiredBy:\n"
    for ((i=0;i<${#rbpkgs[@]};i++)); do
        echo "${rbpkgs[$i]}"
    done
}

# do_buildrequiredby(pkg)
# do_buildrequiredby(pkg, sqlbinfile, sqlsrcfile)
do_buildrequiredby() {
    if [ $# == 1 ]; then
        check_yumrepo
        if [ $? != 0 ]; then
            exit
        fi
        subpkgs=($1)
    elif [ $# == 3 ]; then
        sql_bin_file=$2
        sql_src_file=$3
        local bins=$(get_bins_fromsqlfile "$1")
        subpkgs=($bins)
    else
        usage_buildrequiredby; exit
    fi
    __do_buildrequiredby "${subpkgs[*]}" | column -t -s '|'
}

# do_whatprovides(req, sqlbinfile="")
do_whatprovides() {
    if [ $# -lt 1 ]; then
        usage_whatprovides; exit
    fi
    if [ $# == 1 ]; then
        check_yumrepo
        if [ $? != 0 ]; then
            exit
        fi
    else
        sql_bin_file=$2
    fi
    local rely=$1
    local bin=$(get_whatprovides "$rely")
    if [ -z "$bin" ]; then
        echo "Not Found package that provides \"$rely\""
        exit
    fi
    local src=$(get_source "$bin")
    {
        printf "%s|%s|%s\n" "# Provides" "# Binary" "# Source"
        printf "%s|%s|%s\n" "$rely" "$bin" "$src"
    } | column -t -s '|'
    
    echo ""
    if [ -n "$src" ]; then
        osc search --package $src 2> /dev/null
    fi
}

# do_whatrequires(req, sqlbinfile="")
do_whatrequires() {
    if [ $# -lt 1 ]; then
        usage_whatrequires; exit
    fi
    if [ $# == 1 ]; then
        check_yumrepo
        if [ $? != 0 ]; then
            exit
        fi
    else
        sql_bin_file=$2
    fi
    local req=$1
    local bins=$(get_whatrequires "$req")
    {
        printf "%s|%s|%s\n" "# Symbol" "# Requires-bin" "# Requires-src"
        for bin in $bins; do
            local src=$(get_source "$bin")
            printf "%s|%s|%s\n" "$req" "$bin" "$src"
        done
    } | column -t -s '|'
}

# do_whatbuildrequires(req, sqlsrcfile="")
do_whatbuildrequires() {
    if [ $# -lt 1 ]; then
        usage_whatbuildrequires; exit
    fi
    if [ $# == 1 ]; then
        check_yumrepo
        if [ $? != 0 ]; then
            exit
        fi
    else
        sql_src_file=$2
    fi
    local req=$1
    local srcs=$(get_whatbuildrequires "$req")
    echo "$srcs"
}

# get_specfilename(spec)
get_specfilename() {
    local pkg=$(basename "$1")
    pkg=${pkg%%.*}
    echo "$pkg"
}

# get_requiresbyspec(spec, tag)
get_requiresbyspec() {
    local spec=$1
    local tag=$2
    local reqs=$(cat "$spec" | grep -E "^$tag:" |\
        sed -r "s/^$tag:\s+//g" | sed -r 's/ +(>|<|=)+ +([0-9]+[\.0-9]*|\%\{[0-9a-zA-Z]+\}[-\%\{0-9a-zA-Z\}]*)//g' |\
        sed -r 's/ +(with|and|or) +/\)\n\(/g' | sed -r 's/\s+/\n/g' | sed -r 's/^\((.*)\)$/\1/g' |\
        sort | uniq
    )
    echo "$reqs"
}

# __do_requires(reqs)
__do_requires() {
    local reqs="$1"
    local srcs=()
    printf "%s\t%s\t%s\t%s\n" "# Package" "# Requires" "# Requires-bin" "# Requires-src"
    for rely in $reqs; do
        local bin=$(get_whatprovides "$rely")
        local src="Not-Found"
        if [ -z "$bin" ]; then
            bin="Not-Found"
        else
            src=$(get_source "$bin")
            if [ -z "$src" ]; then
                src=$bin
            fi
        fi
        srcs=(${srcs[@]} $src)
        printf "%s\t%s\t%s\t%s\n" "$pkg" "$rely" "$bin" "$src"
    done
    srcs=($(array_uniq "${srcs[*]}"))
    echo ""
    echo "# Requires Package"
    for ((i=0;i<${#srcs[@]};i++)); do
        echo "${srcs[$i]}"
    done
}

# do_requires(pkg, sqlbinfile="", sqlsrcfile="")
# do_requires(specfile)
do_requires() {
    if [ $# == 1 ]; then
        check_yumrepo
        if [ $? != 0 ]; then
            exit
        fi
    elif [ $# == 3 ]; then
        sql_bin_file=$2
        sql_src_file=$3
    else
        usage_requires; exit
    fi

    local pkg=""
    local reqs=""
    # spec file
    if [ -f "$1" ]; then
        local spec=$1
        pkg=$(get_specfilename "$spec")
        if [ -z "$pkg" ]; then
            echo "spec file name is invalid"; exit
        fi
        reqs=$(get_requiresbyspec "$spec" "Requires")
    else
        pkg=$1
        reqs=$(get_requires "$pkg")
    fi

    __do_requires "$reqs"
}

# __do_provides(pkgs)
__do_provides() {
    printf "%s|%s\n" "# Package" "# Provides"
    for pkg in $pkgs; do
        pros=$(get_provides "$pkg")
        for pro in $pros; do
            printf "%s|%s\n" $pkg $pro
        done
    done
}

# do_provides(pkg)
do_provides() {
    local pkgs=""
    if [ $# == 1 ]; then
        pkgs=$1
    elif [ $# == 2 ]; then
        pkgs=$(get_bins_fromobs "$1" "$2")
    else
        usage_provides; exit
    fi
    __do_provides "$pkgs" | column -t -s '|'
}

# array_uniq("${array[*]}")
array_uniq() {
    local a=($1)
    a=($(echo "${a[*]}" | sed 's/ /\n/g' | sort | uniq))
    echo "${a[@]}"
}

# array_contain("${array[*]}", b)
array_contain() {
    local a=($1)
    local b=$2
    local flag=0
    for ((i=0;i<${#a[@]};i++)); do
        if [ "${a[$i]}" = "$b" ]; then
            flag=1
            break
        fi
    done
    echo "$flag"
}

# get_requires_pkgarray(pkg)
get_requires_pkgarray() {
    local pkg=$1
    local array=()
    local reqs=$(get_requires "$pkg")
    for rely in $reqs; do
        local bin=$(get_whatprovides "$rely")
        local src=""
        if [ -z "$bin" ]; then
            continue
        else
            src=$(get_source "$bin")
            if [ -z "$src" ]; then
                src=$bin
            fi
        fi
        array=(${array[@]} $src)
    done
    echo "${array[@]}"
}

get_requirespkgs() {
    local pkgs=($1)
    local reqpkgs=()

    for ((i=0;i<${#pkgs[@]};i++)); do
        pkg=${pkgs[$i]}
        srcs=($(get_requires_pkgarray $pkg))
        srcs=($(array_uniq "${srcs[*]}"))
        reqpkgs=(${reqpkgs[@]} ${srcs[@]})
    done
    reqpkgs=($(array_uniq "${reqpkgs[*]}"))
    echo "${reqpkgs[*]}"
}

# __do_installdep(array, pkgship, outfile)
__do_installdep() {
    local array=($1)
    local pkgship=($2)
    local outfile=$3
    array=(${array[@]} ${pkgship[@]})

    while [ ${#array[@]} != 0 ]; do
        local reqpkgs=()
        for ((i=0;i<${#array[@]};i++)); do
            pkg=${array[$i]}
            local srcs=()
            local reqs=$(get_requires "$pkg")
            for rely in $reqs; do
                local bin=$(get_whatprovides "$rely")
                local src=""
                if [ -z "$bin" ]; then
                    continue
                else
                    src=$(get_source "$bin")
                    if [ -z "$src" ]; then
                        src=$bin
                    fi
                fi
                printf "%s\t%s\t%s\t%s\n" $pkg $rely $bin $src
                srcs=(${srcs[@]} $src)
            done
            srcs=($(array_uniq "${srcs[*]}"))
            reqpkgs=(${reqpkgs[@]} ${srcs[@]})
        done
        array=($(array_uniq "${reqpkgs[*]}"))
        tmp=()
        for ((j=0;j<${#array[@]};j++)); do
            if [ $(array_contain "${pkgship[*]}" "${array[$j]}") == 0 ]; then
                tmp=(${tmp[@]} ${array[$j]})
            fi
        done
        if [ ${#tmp[@]} != 0 ]; then
            pkgship=(${pkgship[@]} ${tmp[@]})
        fi
        array=(${tmp[@]})
    done

    printf "\nDependencies:\n"
    #echo "${pkgship[*]}"
    {
        for ((i=0;i<${#pkgship[@]};i++)); do
            echo "${pkgship[$i]}"
        done
    } | tee $outfile
}

# do_installdep(pkglist, outfile="installdep.txt")
# do_installdep(pkglist, sqlbinfile, sqlsrcfile, outfile="installdep.txt")
do_installdep() {
    local outfile="installdep.txt"
    if [ $# == 1 ] || [ $# == 2 ]; then
        check_yumrepo
        if [ $? != 0 ]; then
            exit
        fi
        if [ -n "$2" ]; then
            outfile=$2
        fi
    elif [ $# == 3 ] || [ $# == 4 ]; then
        sql_bin_file=$2
        sql_src_file=$3
        if [ -n "$4" ]; then
            outfile=$4
        fi
    else
        usage_installdep; exit
    fi
    local pkgs=$(get_list "$1")
    local array=()

    for pkg in $pkgs; do
        array=(${array[@]} $pkg)
    done

    printf "%s\t%s\t%s\t%s\n" "# Package" "# Requires-sym" "# Requires-bin" "# Requires-src"
    __do_installdep "${array[*]}" "" "$outfile"
}

# do_buildrequires(pkg, sqlbinfile, sqlsrcfile)
# do_buildrequires(specfile)
do_buildrequires() {
    local brqs=""
    if [ $# == 1 ]; then
        local spec=$1
        local pkg=$(basename "$spec")
        pkg=${pkg%%.*}
        if [ -z "$pkg" ]; then
            echo "spec file name invalid"; exit
        fi
        brqs=$(cat "$spec" | grep -E "^BuildRequires:" |\
            sed -r 's/^BuildRequires:\s+//g' | sed -r 's/ +(>|<|=)+ +[0-9]+[\.0-9]*//g' |\
            sed -r 's/ +(with|and|or) +/\)\n\(/g' | sed -r 's/\s+/\n/g' | sed -r 's/^\((.*)\)$/\1/g' |\
            sort | uniq
        )
    elif [ $# == 3 ]; then
        local pkg=$1
        sql_bin_file=$2
        sql_src_file=$3
        brqs=$(get_buildrequires "$pkg")
    else
        usage_buildrequires; exit
    fi
    __do_requires "$brqs"
}

# content=/build/<project>/<repository>/<arch>/<package>/_buildinfo
__do_buildinfo() {
    local content=$1
    local infos=$(osc api -X GET "$content" 2> /dev/null)
    local bins=$(echo "$infos" | grep "<bdep" | grep -v "preinstall" | sed -r 's/ +<bdep +name="([^"]+)".*$/\1/g')
    local srcs=()
    for bin in $bins; do
        src=$(get_source "$bin")
        if [ -z "$src" ]; then
            src=$(echo "$bin" | sed -r 's/-(devel|help|libs)$//g')
        fi
        if [ $(array_contain "${srcs[*]}" $src) == 0 ]; then
            srcs=(${srcs[@]} $src)
            echo "$src"
        fi
    done
}

# _get_bdep_tagval(info, tag)
__get_bdep_tagval() {
    local val=$(echo "$1" | sed -r "s/.*$2=\"([^\"]+)\".*$/\1/g" | grep -v "<bdep")
    echo "$val"
}

# do_buildinfo(prj/repo/arch/pkg)
do_buildinfo() {
    local content="/build/$1/_buildinfo"
    local infos=$(osc api -X GET "$content" 2> /dev/null)
    local bdeps=$(echo "$infos" | grep "<bdep" | grep -v "preinstall")
    local pkgs=()
    OLD_IFS="$IFS"; IFS=$'\n'
    for info in $bdeps; do
        local name=$(__get_bdep_tagval "$info" name)
        local epoch=$(__get_bdep_tagval "$info" epoch)
        local version=$(__get_bdep_tagval "$info" version)
        local release=$(__get_bdep_tagval "$info" release)
        local pkg="$name-$version-$release"
        if [ -n "$epoch" ]; then
            pkg="$name-$epoch:$version-$release"
        fi
        pkgs=(${pkgs[@]} $pkg)
    done
    IFS="$OLD_IFS"
    pkgs=($(array_uniq "${pkgs[*]}"))
    for ((i=0;i<${#pkgs[@]};i++)); do
        echo "${pkgs[$i]}"
    done
}

# do_builddep(prj/repo/arch/pkg)
# do_builddep(pkglist, outfile="builddep.txt")
# do_builddep(pkglist, sqlbinfile, sqlsrcfile, outfile="builddep.txt")
do_builddep() {
    local outfile="builddep.txt"
    if [ $# == 1 ] || [ $# == 2 ]; then
        check_yumrepo
        if [ $? != 0 ]; then
            exit
        fi
        if [ $# == 1 ]; then
            sep=$(echo "$1" | grep "/")
            if [ -n "$sep" ]; then
                # /build/<project>/<repository>/<arch>/<package>/_buildinfo
                local content="/build/$1/_buildinfo"
                 __do_buildinfo "$content"
                exit
            fi
        elif [ -n "$2" ]; then
            outfile=$2
        fi
    elif [ $# == 3 ] || [ $# == 4 ]; then
        sql_bin_file=$2
        sql_srl_file=$3
        if [ -n "$4" ]; then
            outfile=$4
        fi
    else
        usage_builddep; exit
    fi
    local pkgs=$(get_list "$1")
    local array=()

    for pkg in $pkgs; do
        array=(${array[@]} $pkg)
    done

    printf "%s\t%s\t%s\t%s\n" "# Package" "# Requires-sym" "# Requires-bin" "# Requires-src"
    # buildrequires
    local pkgship=()
  	for ((i=0;i<${#array[@]};i++)); do
		pkg=${array[$i]}
		local srcs=()
		local brqs=$(get_buildrequires "$pkg")
		for rely in $brqs; do
			local bin=$(get_whatprovides "$rely")
			local src=""
			if [ -z "$bin" ]; then
				continue
			else
				src=$(get_source "$bin")
				if [ -z "$src" ]; then
					src=$bin
				fi
			fi
			printf "%s\t%s\t%s\t%s\n" $pkg $rely $bin $src
			srcs=(${srcs[@]} $src)
		done
		srcs=($(array_uniq "${srcs[*]}"))
		pkgship=(${pkgship[@]} ${srcs[@]})
	done
    echo "------ ------ ------ ------"
    __do_installdep "${array[*]}" "${pkgship[*]}" "$outfile"
}

# do_pkgship(pkglist, outfile="pkgship.txt")
# do_pkgship(pkglist, sqlbinfile, sqlsrcfile, outfile="pkgship.txt")
do_pkgship() {
    local outfile="pkgship.txt"
    if [ $# == 1 ] || [ $# == 2 ]; then
        check_yumrepo
        if [ $? != 0 ]; then
            exit
        fi
        if [ -n "$2" ]; then
            outfile=$2
        fi
    elif [ $# == 3 ] || [ $# == 4 ]; then
        sql_bin_file=$2
        sql_src_file=$3
        if [ -n "$4" ]; then
            outfile=$4
        fi
    else
        usage_pkgship; exit
    fi
    local pkgs=$(get_list "$1")
    local array=()

    for pkg in $pkgs; do
        array=(${array[@]} $pkg)
    done

    local pkgship=()
    local bins=()
    printf "%s\t%s\t%s\t%s\t%s\n" "# Package" "Requires-type" "# Requires-sym" "# Requires-bin" "# Requires-src"
    while [ ${#array[@]} != 0 ]; do
        local reqpkgs=()
        for ((i=0;i<${#array[@]};i++)); do
            pkg=${array[$i]}
            local srcs=()
            local brqs=$(get_buildrequires "$pkg")
            for rely in $brqs; do
                local bin=$(get_whatprovides "$rely")
                local src=""
                if [ -z "$bin" ]; then
                    continue
                else
                    if [ $(array_contain "${bins[*]}" $bin) == 1 ]; then
                        continue
                    else
                        bins=(${bins[@]} $bin)
                    fi
                    src=$(get_source "$bin")
                    if [ -z "$src" ]; then
                        src=$bin
                    fi
                fi
                printf "%s\t%s\t%s\t%s\t%s\n" $pkg "build" $rely $bin $src
                srcs=(${srcs[@]} $src)
            done
            local reqs=$(get_requires "$pkg")
            for rely in $reqs; do
                local bin=$(get_whatprovides "$rely")
                local src=""
                if [ -z "$bin" ]; then
                    continue
                else
                    if [ $(array_contain "${bins[*]}" $bin) == 1 ]; then
                        continue
                    else
                        bins=(${bins[@]} $bin)
                    fi
                    src=$(get_source "$bin")
                    if [ -z "$src" ]; then
                        src=$bin
                    fi
                fi
                printf "%s\t%s\t%s\t%s\t%s\n" $pkg "install" $rely $bin $src
                srcs=(${srcs[@]} $src)
            done
            srcs=($(array_uniq "${srcs[*]}"))
            reqpkgs=(${reqpkgs[@]} ${srcs[@]})
        done
        array=($(array_uniq "${reqpkgs[*]}"))
        tmp=()
        for ((j=0;j<${#array[@]};j++)); do
            if [ $(array_contain "${pkgship[*]}" "${array[$j]}") == 0 ]; then
                tmp=(${tmp[@]} ${array[$j]})
            fi
        done
        if [ ${#tmp[@]} != 0 ]; then
            pkgship=(${pkgship[@]} ${tmp[@]})
        fi
        array=(${tmp[@]})
    done

    #echo "${pkgship[*]}"
    {
        for ((i=0;i<${#pkgship[@]};i++)); do
            echo "${pkgship[$i]}"
        done
    } | tee $outfile
}

do_getbin() {
    if [ $# != 1 ]; then
        usage_getbin; exit
    fi
    # project/package/repo/arch/binaryname
    local prj=""
    eval $(echo "$1" | awk -F "/" '{
        if (NF >= 5) {
            printf("prj=%s;pkg=%s;repo=%s;arch=%s;bname=%s;", $(NF-4), $(NF-3), $(NF-2), $(NF-1), $NF)
        }
    }')
    if [ -z "$prj" ]; then
        echo "url format error"
        exit
    fi
    # /build/project/repo/arch/package/binaryname
    local content="/build/$prj/$repo/$arch/$pkg/$bname"

    echo "downloading $bname ..."
    osc api -X GET "$content" > $bname 2> /dev/null
}

# do_getbinaries(prj, repo, arch, pkgs)
do_getbinaries() {
    if [ $# != 4 ]; then
        usage_getbinaries; exit
    fi
    local pkgs=$(get_list "$4")

    for pkg in $pkgs; do
        osc getbinaries $1 $pkg $2 $3
    done
}

do_getfile() {
    if [ $# != 1 ]; then
        usage_getfile; exit
    fi
    # xxx/project/package/filename?xxxx
    local url=$(echo "$1" | sed 's/\?.*//')
    # xxx/project/package/filename
    local prj=""
    eval $(echo "$url" | awk -F "/" '{
        if (NF >= 3) {
            printf("prj=%s;pkg=%s;fname=%s;", $(NF-2), $(NF-1), $NF)
        }
    }')
    if [ -z "$prj" ]; then
        echo "url format error"
        exit
    fi
    # project/package/filename
    local content="$prj/$pkg/$fname"
    local newfile=${fname##*:}

    echo "downloading $newfile ..."
    osc co "$content" 2> /dev/null
    if [ $? == 0 ] && [ "$fname" != "$newfile" ]; then
        mv $fname $newfile
    fi
}

do_getbinlist() {
    if [ $# != 2 ]; then
        usage_getbinlist; exit
    fi
    local prj=$1
    local pkg=$2
    local results=$(osc results $prj $pkg 2> /dev/null)
    local repo_arch=$(echo "$results" | awk '{print $1"/"$2}')
    k=1
    for i in $(echo "$repo_arch"); do
        # /build/project/repo/arch/package
        local content="/build/$prj/$i/$pkg"
        echo -e "${COLOR_GREEN}$k) $i:${COLOR_NONE}"
        osc api -X GET "$content" 2> /dev/null
        ((k++))
    done
}

do_filterout() {
    if [ $# != 2 ]; then
        usage_filterout; exit
    fi
    local prjs=$(get_list "$1")
    local pkgs=$(get_list "$2")
    local outpkgs=()
    local allpkgs=()

    for prj in $prjs; do
        tmp=($(osc ls "$prj" 2> /dev/null))
        allpkgs=(${allpkgs[@]} ${tmp[@]})
    done
    allpkgs=($(array_uniq "${allpkgs[*]}"))
    for pkg in $pkgs; do
        existflag=0
        for ((i=0;i<${#allpkgs[@]};i++)); do
            if [ "${allpkgs[$i]}" = "$pkg" ]; then
                existflag=1
                break
            fi
        done
        if [ $existflag == 0 ]; then
            outpkgs=(${outpkgs[@]} $pkg)
        fi
    done
    outpkgs=($(array_uniq "${outpkgs[*]}"))
    for ((i=0;i<${#outpkgs[@]};i++)); do
        echo "${outpkgs[$i]}"
    done
}

do_list() {
    if [ $# != 4 ]; then
        usage_list; exit
    fi
    local obs_project=$1
    local obs_repo=$2
    local obs_arch=$3
    local state=$4
    local pkgs=$(osc pr $obs_project -s $state -r $obs_repo -a $obs_arch -q -V 2> /dev/null | sed 1d | sed '$d' | sed '$d' | awk '{print $2}')

    if [ -n "$pkgs" ]; then
        echo "$pkgs"
    fi
}

do_help() {
    case $1 in
        "branch"|"br")
            usage_branch
            ;;
        "checkout"|"co")
            usage_checkout
            ;;
        "importsrcpkg"|"isp")
            usage_importsrcpkg
            ;;
        "pkgresults"|"pr")
            usage_pkgresults
            ;;
        "changename"|"cn")
            usage_changename
            ;;
        "setflag"|"sf")
            usage_setflag
            ;;
        "unresolved"|"ur")
            usage_unresolved
            ;;
        "requiredby"|"rb")
            usage_requiredby
            ;;
        "buildrequiredby"|"brb")
            usage_buildrequiredby
            ;;
        "whatprovides"|"wp")
            usage_whatprovides
            ;;
        "whatrequires"|"wr")
            usage_whatrequires
            ;;
        "whatbuildrequires"|"wbr")
            usage_whatbuildrequires
            ;;
        "requires"|"rq")
            usage_requires
            ;;
        "provides"|"prov")
            usage_provides
            ;;
        "installdep"|"idep")
            usage_installdep
            ;;
        "buildrequires"|"brq")
            usage_buildrequires
            ;;
        "builddep"|"bdep")
            usage_builddep
            ;;
        "buildinfo"|"binfo")
            usage_buildinfo
            ;;
        "pkgship"|"ps")
            usage_pkgship
            ;;
        "getbin"|"gb")
            usage_getbin
            ;;
        "getbinaries"|"gbs")
            usage_getbinaries
            ;;
        "getbinlist"|"gbl")
            usage_getbinlist
            ;;
        "getfile"|"gf")
            usage_getfile
            ;;
        "filterout"|"flo")
            usage_filterout
            ;;
        "list"|"ls")
            usage_list
            ;;
        *)
            usage
            ;;
    esac
}

main() {
    local subcmd=$1

    if [ $# -gt 0 ]; then
        shift
    fi

    case $subcmd in
        "branch"|"br")
            do_branch "$@"
            ;;
        "checkout"|"co")
            do_checkout "$@"
            ;;
        "importsrcpkg"|"isp")
            do_importsrcpkg "$@"
            ;;
        "pkgresults"|"pr")
            do_pkgresults "$@"
            ;;
        "changename"|"cn")
            do_changename "$@"
            ;;
        "setflag"|"sf")
            do_setflag "$@"
            ;;
        "unresolved"|"ur")
            do_unresolved "$@"
            ;;
        "requiredby"|"rb")
            do_requiredby "$@"
            ;;
        "buildrequiredby"|"brb")
            do_buildrequiredby "$@"
            ;;
        "whatprovides"|"wp")
            do_whatprovides "$@"
            ;;
        "whatrequires"|"wr")
            do_whatrequires "$@"
            ;;
        "whatbuildrequires"|"wbr")
            do_whatbuildrequires "$@"
            ;;
        "requires"|"rq")
            do_requires "$@"
            ;;
        "provides"|"prov")
            do_provides "$@"
            ;;
        "installdep"|"idep")
            do_installdep "$@"
            ;;
        "buildrequiers"|"brq")
            do_buildrequires "$@"
            ;;
        "builddep"|"bdep")
            do_builddep "$@"
            ;;
        "buildinfo"|"binfo")
            do_buildinfo "$@"
            ;;
        "pkgship"|"ps")
            do_pkgship "$@"
            ;;
        "getbin"|"gb")
            do_getbin "$@"
            ;;
        "getbinaries"|"gbs")
            do_getbinaries "$@"
            ;;
        "getbinlist"|"gbl")
            do_getbinlist "$@"
            ;;
        "getfile"|"gf")
            do_getfile "$@"
            ;;
        "filterout"|"flo")
            do_filterout "$@"
            ;;
        "list"|"ls")
            do_list "$@"
            ;;
        "help"|"?"|"h")
            do_help "$@"
            ;;
        *)
            usage
            ;;
    esac

}

main "$@"

